import $ from 'jquery'
import { AppLoader } from './app_loader'
import { ConfigValidatorService } from './element/service/config_validator'
import { ThemeVar } from './lib/abstract/style/theme_var'
import { BodyHandler } from './lib/body_handler'
import { DependencyManager } from './lib/dependency'
import { DocumentManager } from './lib/document_manager'
import { EventEmitter } from './lib/event_emitter'
import { LogStyle } from './lib/logger'
// import { runSelectorPerformanceTest } from './lib/selector_performance'
import { getSwalStyleElements } from './lib/swal_toast'
import { UrlHandler } from './lib/url_handler'
import { ToolKit } from './lib/utils/toolkit'
import { Menu } from './menu/menu'
import { ConfigManager } from './module/config_manager'
import { StyleOrder } from './test/style_order'
// import { TestElementQuery } from './test/test_element_query'
import {
  addGmStyle,
  BodyAttrs,
  BUILD_CONFIG,
  checkAllResourceIntegrity,
  getGmStyleElements,
  logger,
  pageJQueryVersion,
} from './types/constants'
import { SYMBOLS } from './types/interfaces'
import { LoadingThemeService } from './user_center/tab/personalization/loading_theme/service'

// 【document-start】【同步立即执行】应用初始化阶段
(function initializeApp() {
  'use strict'

  // 1. 手动挂载到全局（这里必须得手动，不然导入语句会被忽略掉）
  window.$ = $
  window.jQuery = $

  // 2. 应用加载样式
  DocumentManager.getInstance().applyLoadingStyles(true, { target: 'document' })

  // 初始化脚本运行标志
  if (!window.__SCRIPT_RUN_FLAGS__) {
    window.__SCRIPT_RUN_FLAGS__ = {}
    window.__SCRIPT_RUN_FLAGS__.platformSupported = false
  }

  // 3. 检查是否已运行
  if (window.__SCRIPT_RUN_FLAGS__[BUILD_CONFIG.PROJECT_NAME])
    return

  window.__SCRIPT_RUN_FLAGS__[BUILD_CONFIG.PROJECT_NAME] = true

  window.__SCRIPT_RUN_FLAGS__.platformSupported = ToolKit.browser.platform.withPlatformCheck(async () => {
    // 4. 打印应用信息
    logger.printAppInfo(BUILD_CONFIG.NAME, BUILD_CONFIG.VERSION)

    // 5. 注入基础样式
    addGmStyle()

    // 6. 初始化 body
    const bodyHandler = BodyHandler.getInstance()
    bodyHandler.init()

    // 7. 初始化主题
    await logger.executeWithLogging('加载主题', () => ThemeVar.getInstance().init(), {
      collapsed: true,
      color: LogStyle.groupHeader,
    })

    // 8. 立即显示加载动画
    LoadingThemeService.getInstance()
  })
})()

// 【document-end】【异步延迟执行】服务初始化阶段
function startApp() {
  // 检查平台是否支持
  if (!window.__SCRIPT_RUN_FLAGS__.platformSupported) {
    // 移除加载样式
    DocumentManager.getInstance().applyLoadingStyles(false, { target: 'document' })
    return
  }

  // 检查是否已运行
  if (window.__SCRIPT_RUN_FLAGS__[`${BUILD_CONFIG.PROJECT_NAME}_DOMReady`])
    return

  window.__SCRIPT_RUN_FLAGS__[`${BUILD_CONFIG.PROJECT_NAME}_DOMReady`] = true

  ToolKit.browser.platform.withPlatformCheck(async () => {
    try {
      // 1. 确保 DOM 已就绪
      await ToolKit.async.waitForDOMReady()

      // 2. 初始化依赖检测
      await logger.executeWithLogging('加载依赖', () => initializeDependencies(), {
        collapsed: true,
        color: LogStyle.groupHeader,
      })

      // 3. 初始化 URL
      const urlHandler = UrlHandler.getInstance()
      urlHandler.startTracking()

      // 4. 加载服务
      const app = new AppLoader()
      await app.bootstrap()

      // 5. 注册菜单命令（需要在服务加载后，功能开关引用到了服务元素的显隐状态）
      const menu = new Menu()
      await menu.init()

      // 6. 保护关键元素
      protectCriticalElements()

      // 7. 显示事件发射器信息
      logger.attention('事件发射器信息', EventEmitter.getInstance().getStats())

      // 8. 执行测试
      await logger.executeWithLogging('执行测试', async () => {
        // 1）主题样式在自定义样式之前
        StyleOrder.getInstance().startMonitoring()

        // 2）检测元素隐藏规则
        const configValidator = ConfigValidatorService.getInstance()
        configValidator.validateAllConfigs()

        // 3）选择器性能测试
        // await runSelectorPerformanceTest()

        // 4）校验资源完整性
        await checkAllResourceIntegrity()

        // 9. 测试元素查询
        // const testElementQuery = TestElementQuery.getInstance()
        // testElementQuery.startTest()
      }, {
        collapsed: true,
        color: LogStyle.groupHeader,
      })

      // 7. 打印所有存储变量
      await logger.executeWithLogging('应用数据', () => {
        const configManager = ConfigManager.getInstance()
        logger.tip(`存储数据`, configManager.storage.getAll({ useNamespace: false, useDomainIsolation: true, includeGlobal: true }))
        // configManager.storage.deleteBatch({ useNamespace: false, useDomainIsolation: false, includeGlobal: true })
        // logger.warn('存储数据删除后：', configManager.storage.getAll({ useNamespace: false, useDomainIsolation: false, includeGlobal: true }))
        logger.tip(`功能配置`, configManager.featureHandlers)
      })
    }
    catch (e: any) {
      logger.error(`${SYMBOLS.STATUS.ERROR} 应用初始化失败，请联系油猴脚本开发者`, e)
    }
  }, { showMessage: false })
}

// 启动应用
startApp()

/**
 * 初始化应用依赖
 */
async function initializeDependencies() {
  logger.important(`${SYMBOLS.UI.SETTINGS} 正在检测平台环境依赖...`)
  logger.info(pageJQueryVersion ? `平台自带 jQuery 版本：${pageJQueryVersion}` : '平台未使用 jQuery')
  logger.important(`${SYMBOLS.UI.SETTINGS} 正在初始化环境依赖...`)
  // 加载依赖
  const dependencyManager = DependencyManager.getInstance()
  await dependencyManager.loadAll()
  dependencyManager.printDetailedReport()
}

/**
 * 保护关键元素不被修改或删除
 */
function protectCriticalElements() {
  // 1. 保护弹窗样式
  getSwalStyleElements().forEach((styleElement) => {
    ToolKit.ui.style.markBaiduSearchElement(styleElement)
  })

  // 2. 保护 GM 样式
  getGmStyleElements().forEach((styleElement) => {
    ToolKit.ui.style.markBaiduSearchElement(styleElement)
  })

  // 3. 保护项目元素（不包含Shadow DOM）
  $(`[${BodyAttrs.PROJECT_MODULE}="true"]`).each((_, element) => {
    ToolKit.ui.style.markBaiduSearchElement(element)
  })
}
